home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Plug-in - WireFrame Renderer / SR_PointPipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  6.9 KB  |  285 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        SR_PointPipe.c                                              **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **     Purpose:     Sample Renderer point pipeline                              **
  7.  **                                                                          **
  8.  **                                                                          **
  9.  **                                                                          **
  10.  **     Copyright (C) 1996 Apple Computer, Inc.  All rights reserved.          **
  11.  **                                                                          **
  12.  **                                                                          **
  13.  *****************************************************************************/
  14. #include <stdlib.h>
  15. #include <assert.h>
  16.  
  17. #include "QD3D.h"
  18. #include "QD3DMath.h"
  19. #include "QD3DErrors.h"
  20.  
  21. #include "SR.h"
  22. #include "SR_ClipUtilities.h"
  23.  
  24.  
  25. /*===========================================================================*\
  26.  *
  27.  *    Routine:    SR_PointPipe()
  28.  *
  29.  *    Comments:    Used for points, and for lines and triangles in point mode.
  30.  *
  31. \*===========================================================================*/
  32.  
  33. TQ3Status SR_PointPipe(
  34.     TSRPrivate             *srPrivate, 
  35.     TQ3Point3D            *localVertices,
  36.     long                numVertices,
  37.     long                sizeOfLocalVertices,
  38.     TQ3ColorRGB            *color,
  39.     TQ3Vector3D            *normal,
  40.     long                mode)
  41. {
  42.     TQ3Status            status;
  43.     unsigned long        i;
  44.     TQ3RationalPoint4D    *deviceVertices         = NULL;
  45.     TQ3RationalPoint4D    *clippedVertices         = NULL;
  46.     TQ3RationalPoint4D    *renderVertices         = NULL;
  47.     long                clipFound, allOut;
  48.     unsigned long        *clipFlags                 = NULL;
  49.     long                *clippedVerticesFlags     = NULL;
  50.     PointFunction2D        pointFunction;
  51.     
  52.     /*
  53.      *  Get the appropriate rasterization function for the points
  54.      *  (depth, whether window is clipped or not, etc.
  55.      */
  56.     pointFunction = 
  57.         ((TSRRasterFunctions *)(srPrivate->currentRasterFunctions))->pointFunction;
  58.  
  59.     /*
  60.      *  If we're in "DO_POLYGON" mode, then we have to consider whether
  61.      *  we need to cull or not.
  62.      */
  63.     if (mode == DO_POLYGON) {
  64.         assert(normal != NULL);
  65.         
  66.         /*
  67.          *  We will attempt to do culling if the rank of the upper-left 3x3 
  68.          *  submatrix of the local-to-world matrix is at least 2.  
  69.          *  A rank of 3 means that volumes are transformed into volumes.  
  70.          *  A rank of 2 means that volumes are transformed onto a plane.  
  71.          *  For a rank of 1 (line) or 0 (point), we bypass the culling stage 
  72.          *  and just render the line or point.
  73.          */
  74.         if (srPrivate->backfacingStyle == kQ3BackfacingStyleRemove &&
  75.             (srPrivate->normalLocalToWorldRank >= 2)) {
  76.             
  77.             if (normal->x * normal->x + 
  78.                 normal->y * normal->y + 
  79.                 normal->z * normal->z < 1.e-10) {
  80.                 /* 
  81.                  *  Normal vector's length is < 1.e-10 meaning the 
  82.                  *  polygon is degenerate 
  83.                  */
  84.                 return (kQ3Success);
  85.             }
  86.             
  87.             /*
  88.              *  If the local-to-world matrix has a rank of 2, then the eye
  89.              *  in local coordinates is a vector even if the view is a 
  90.              *  perspective transformation.
  91.              */
  92.             if ((srPrivate->cameraType == kQ3CameraTypeOrthographic) ||
  93.                 (srPrivate->normalLocalToWorldRank == 2)) {
  94.  
  95.                 /* Orthographic projection */
  96.                 if ((normal->x * srPrivate->eyeVectorInLocalCoords.x + 
  97.                      normal->y * srPrivate->eyeVectorInLocalCoords.y + 
  98.                      normal->z * srPrivate->eyeVectorInLocalCoords.z < 0.0) ^
  99.                     ((srPrivate->orientationStyle == 
  100.                         kQ3OrientationStyleClockwise))) {
  101.                     /* 
  102.                      *  Backfacing so cull it 
  103.                      */
  104.                     return (kQ3Success);
  105.                 }
  106.             } else {
  107.                 TQ3Point3D                *point;
  108.                 TQ3Vector3D                eyeVector;
  109.                 
  110.                 /* Perspective projection */
  111.                 point = localVertices;
  112.                 eyeVector.x = srPrivate->eyePointInLocalCoords.x - point->x;
  113.                 eyeVector.y = srPrivate->eyePointInLocalCoords.y - point->y;
  114.                 eyeVector.z = srPrivate->eyePointInLocalCoords.z - point->z;
  115.                 if ((normal->x * eyeVector.x + 
  116.                      normal->y * eyeVector.y + 
  117.                      normal->z * eyeVector.z < 0.0) ^
  118.                     ((srPrivate->orientationStyle == 
  119.                         kQ3OrientationStyleClockwise))) {
  120.                     /*
  121.                      *  Backfacing so cull it 
  122.                      */
  123.                     return (kQ3Success);
  124.                 }
  125.             }
  126.         }
  127.     }
  128.  
  129.     status = kQ3Success;
  130.  
  131.     /*
  132.      *  Allocate device-coordinate vertices
  133.      */
  134.     deviceVertices = malloc(numVertices * sizeof(TQ3RationalPoint4D));
  135.     if (deviceVertices == NULL) {
  136.         status = kQ3Failure;
  137.         goto bail;
  138.     }
  139.     
  140.     /*
  141.      *  Transform local-space point vertices to device space
  142.      */
  143.     Q3Point3D_To4DTransformArray(
  144.         localVertices,
  145.         &srPrivate->transforms.localToDC,  
  146.         deviceVertices,
  147.         numVertices,
  148.         sizeOfLocalVertices, 
  149.         sizeof(TQ3RationalPoint4D));
  150.         
  151.     /*
  152.      *  renderVertices are those that will be rendered. If there is a clip,
  153.      *  then we'll set this to the clipped vertices instead.
  154.      */
  155.     renderVertices = deviceVertices;
  156.     
  157.     /*
  158.      *  Allocate a clip flag for each vertex. Bail if allocation fails.
  159.      */
  160.     clipFlags = malloc(numVertices * sizeof(unsigned long));
  161.     if (clipFlags == NULL) {
  162.         status = kQ3Failure;
  163.         goto bail;
  164.     }
  165.  
  166.     /*
  167.      *  See of we have a clip
  168.      */
  169.     SRPointList_ClipTestVertices(
  170.         deviceVertices, 
  171.         clipFlags, 
  172.         numVertices, 
  173.         &srPrivate->clipPlanesInDC[0], 
  174.         &clipFound, 
  175.         &allOut, 
  176.         sizeof(TQ3RationalPoint4D));
  177.         
  178.     if (allOut) {
  179.         /*
  180.          *  Return now, as nothing need be drawn
  181.          */
  182.         goto bail;
  183.     }
  184.     
  185.     if (clipFound) {
  186.         long    numberOfClippedVertices;
  187.  
  188.         /*
  189.          *  Allocate space for clipped vertices. There will be at most
  190.          *  twice as many of these as there are in the original geometric
  191.          *  primitive. Bail if allocation fails.
  192.          */
  193.         clippedVertices = 
  194.             malloc((numVertices << 1) * sizeof(TQ3RationalPoint4D));
  195.         if (clippedVertices == NULL) {
  196.             free(deviceVertices);
  197.             free(clipFlags);
  198.             return (kQ3Failure);
  199.         }
  200.         
  201.         /*
  202.          *  Allocate space for clip flags for vertices. Bail if allocation
  203.          *  fails.
  204.          */
  205.         clippedVerticesFlags = 
  206.             malloc((numVertices << 1) * sizeof(long));
  207.         if (clippedVerticesFlags == NULL) {
  208.             free(clippedVertices);
  209.             free(deviceVertices);
  210.             free(clipFlags);
  211.             return (kQ3Failure);
  212.         }
  213.  
  214.         SRPointList_ClipVertices(
  215.             deviceVertices, 
  216.             sizeof(TQ3RationalPoint4D),
  217.             clippedVertices, 
  218.             sizeof(TQ3RationalPoint4D),
  219.             clipFlags, 
  220.             clippedVerticesFlags,
  221.             numVertices, 
  222.             &numberOfClippedVertices,
  223.             &srPrivate->clipPlanesInDC[0],
  224.             mode);
  225.  
  226.         if (numberOfClippedVertices == 0) {
  227.             goto bail;
  228.         }
  229.         
  230.         renderVertices = clippedVertices;
  231.         numVertices = numberOfClippedVertices;
  232.     }
  233.  
  234.     /*
  235.      *  Divide by homogeneous coordinate
  236.      */
  237.     SRPointList_WDivide(
  238.         renderVertices, 
  239.         numVertices, 
  240.         sizeof(TQ3RationalPoint4D));
  241.  
  242.     /*
  243.      *  Draw each of the points
  244.      */
  245.     for (i = 0; i < numVertices; i++) {
  246.         if (!clipFound || 
  247.             (clippedVerticesFlags && 
  248.              clippedVerticesFlags[i] & SR_DRAW_NEXT)) {
  249.             if ((*pointFunction)(
  250.                     srPrivate,
  251.                     (TQ3Point3D *)&renderVertices[i],
  252.                     color) == kQ3Failure) {
  253.                 return (kQ3Failure);
  254.             }
  255.         }
  256.     }
  257.  
  258. bail:
  259.     /*
  260.      *  Free up any allocated memory
  261.      */
  262.     if (deviceVertices != NULL) {
  263.         free(deviceVertices);
  264.     }
  265.     
  266.     if (clipFlags != NULL) {
  267.         free(clipFlags);
  268.     }
  269.     
  270.     if (clippedVertices != NULL) {
  271.         free(clippedVertices);
  272.     }
  273.     
  274.     if (clippedVerticesFlags != NULL) {
  275.         free(clippedVerticesFlags);
  276.     }
  277.     
  278.     /*
  279.      *  Status may be success or failure, the latter being the case if 
  280.      *  an allocation failed or if the line rasterization function returns
  281.      *  failure.
  282.      */
  283.     return (status);
  284. }
  285.